﻿using System;
using System.Threading;
using System.Threading.Tasks;
using eLoop;


namespace simple
{
    public ref struct ExecutionContextSuppressor
    {
        private readonly bool _restoreFlow;

        /// <summary>
        /// Initializes a new <see cref="ExecutionContextSuppressor"/> instance.
        /// </summary>
        public ExecutionContextSuppressor()
        {
            if (!ExecutionContext.IsFlowSuppressed())
            {
                ExecutionContext.SuppressFlow();
                _restoreFlow = true;
            }
            else
            {
                _restoreFlow = false;
            }
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            if (_restoreFlow)
            {
                ExecutionContext.RestoreFlow();
            }
        }
    }

    
    
    class Program
    {
        static async Task Main(string[] args)
        {
            Scheduler.AddThreadRunner(() =>
            {
                Console.WriteLine("kkk");
            });
            
            // Scheduler.CreateQueueScheduler(true).Schedule0(async (o) =>
            // {
            //     while (true)
            //     {
            //         Console.ReadLine();
            //         
            //         for (int i = 0; i < 10; i++)
            //         {
            //             Console.WriteLine("id>>>>>>>>>" + Thread.CurrentThread.ManagedThreadId);
            //             var value = await Test();
            //
            //             Console.WriteLine("id>>>>>>>>>" + Thread.CurrentThread.ManagedThreadId);
            //         }
            //     }
            //     
            //     
            //     
            // }, null);
            
            
            
            // var threadAllotter = new DefaultThreadSchedulerAllotter(true);
            // var taskThreadScheduler = threadAllotter.Next();
            // taskThreadScheduler.Schedule(new Runnable(), "Thread");
            // taskThreadScheduler.Schedule(&Execute, "Thread");
            // taskThreadScheduler.Schedule0((o) => { Console.WriteLine("Thread"); }, null);
            //
            //
            // var queueAllotter = new DefaultQueueSchedulerAllotter(true);
            // var taskQueueScheduler = queueAllotter.Next();
            // taskQueueScheduler.Schedule(new Runnable(), "Queue");
            // taskQueueScheduler.Schedule(&Execute, "Queue");
            // taskQueueScheduler.Schedule0((o) => { Console.WriteLine("Queue"); }, null);


            //Scheduler.Inline.Schedule0((o) => { Console.WriteLine("Inline"); }, null);
            //Scheduler.ThreadPool.Schedule0((o) => { Console.WriteLine("ThreadPool"); }, null);

            //Scheduler.ThreadPool.Schedule(new ThreadPoolExecutor());


            // DefaultEventSchedulerAllotter allotter = new DefaultEventSchedulerAllotter();
            //
            // var schedule = allotter.Next();
            // schedule.Schedule0(OnEvent, "ssssss");
            
            // Scheduler.CreateThreadScheduler(false).Schedule0(async (o) =>
            // {
            //     Console.WriteLine("id::" + Thread.CurrentThread.ManagedThreadId);
            //     await Task.Run(() =>
            //     {
            //         
            //     });
            //     Console.WriteLine("id::" + Thread.CurrentThread.ManagedThreadId);
            //
            // }, null);

            while (true)
            {
                Thread.Sleep(1);
            }
        }
        static ITaskScheduler scheduler = Scheduler.CreateQueueScheduler(true);
        private static Task<int> Test()
        {
            // using (var Context = new ExecutionContextSuppressor()) ;
            var tcs = new TaskCompletionSource<int>();
            ThreadPool.UnsafeQueueUserWorkItem<object>((o) =>
            {
                using (var Context = new ExecutionContextSuppressor())
                {
                    Console.WriteLine("id>>>>>>Test>>>" + Thread.CurrentThread.ManagedThreadId);
                    tcs.SetResult(99);
                }
            }, null, true);
            
            
            // scheduler.Schedule0((o) =>
            // {
            //     using (var Context = new ExecutionContextSuppressor()) ;
            //     Console.WriteLine("id>>>>>>Test>>>" + Thread.CurrentThread.ManagedThreadId);
            //     tcs.SetResult(99);
            // }, null);
            return tcs.Task;
        }



        private static void OnEvent(object state)
        {
            Console.WriteLine((string)state);
        }

        public static void Execute(object state)
        {
            Console.WriteLine("delegate*___" + state.ToString());
        }

    }

    class Runnable : IRunnable
    {
        public void Execute(object state)
        {
            Console.WriteLine($"IRunnable__{state.ToString()}");
        }
    }

    class ThreadPoolExecutor : IThreadPoolExecutor
    {
        public void Execute()
        {
            Console.WriteLine($"IThreadPoolExecutor");
        }
    }
}